package com.chagee.channel.server.service.biz;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.mts20140618.models.SubmitJobsRequest;
import com.chagee.channel.server.event.service.OssService;
import com.chagee.channel.server.service.dto.MediaInfoDto;
import com.chagee.channel.server.service.dto.VideoTextWaterMarkDto;
import com.chagee.channel.server.service.dto.WatermarkConfigDto;
import com.chagee.channel.server.service.third.AliyunMtsService;
import com.chagee.channel.server.util.WatermarkUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ExecutorService;

/**
 * 视频处理服务
 */
@Slf4j
@Service
public class VideoBizService {

    public static final String WATERMASK_MP4 = "_watermask.mp4";

    @Value("${aliyun.oss.bucketType}")
    private Boolean ALIYUN_OSS_BUCKET_TYPE;
    @Value("${aliyun.oss.privateBucketName}")
    private String ALIYUN_OSS_PRIVATE_BUCKET_NAME;
    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKET_NAME;

    @Value("${video-watermark-config:}")
    private String videoWatermarkConfig;
    @Value("${video-watermark-space:}")
    private String videoWatermarkSpace;

    @Resource
    private AliyunMtsService aliyunMtsService;

    @Resource
    private OssService ossService;

    @Resource(name = "ttlExecutor")
    private ExecutorService threadPoolExecutor;

    /**
     * 同一员工、同一门店多个视频加水印
     * @param ossUrls
     * @param dto
     * @return
     */
    public boolean addTextWaterMark(List<String> ossUrls, VideoTextWaterMarkDto dto){
        if(StrUtil.isEmpty(dto.getTimeStr())){
            dto.setTimeStr(DateUtil.formatDateTime(new Date()));
        }
        log.info("文字水印参数：{}", JSONUtil.toJsonStr(dto));
        // 循环异步处理
        for(String ossUrl : ossUrls){
            threadPoolExecutor.execute(() -> addTextWaterMark(ossUrl, dto));
        }
        return true;
    }

    /**
     * 门店视频添加文字水印
     */
    public boolean addTextWaterMark(String ossUrl, VideoTextWaterMarkDto dto){
        // 先获取到媒体信息
        MediaInfoDto mediaInfoDTO = aliyunMtsService.queryMediaInfo(ossUrl);
        log.info("视频大小信息：{}", JSONUtil.toJsonStr(mediaInfoDTO));
        // 计算水印配置
        WatermarkConfigDto watermarkConfigDto = WatermarkUtil.calcConfig(mediaInfoDTO);
        log.info("计算水印配置：{}", JSONUtil.toJsonStr(watermarkConfigDto));

        int index = ossUrl.indexOf(".com/");
        String path = new String();
        String url = new String();
        if (index != -1) {
            path = ossUrl.substring(index + 5);
            url = ossUrl.substring(0, index + 5);
        }
        // 输入和输出的OSS信息
        String inputBucket;
        String outputBucket;
        if (ALIYUN_OSS_BUCKET_TYPE) {
            inputBucket = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
            outputBucket = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
        } else {
            inputBucket = ALIYUN_OSS_BUCKET_NAME;
            outputBucket = ALIYUN_OSS_BUCKET_NAME;
        }
        String inputObject = path;
        String outputObject = path.split("\\.")[0] + WATERMASK_MP4;
        log.info("转码后视频地址: {}", url + outputObject);

        // 媒体处理模板ID
        String templateId;
        if(mediaInfoDTO.getHeight() >= 1920){
            templateId = "S00000001-200040"; //全高清
        }else if(mediaInfoDTO.getHeight() >= 1280){
            templateId = "S00000001-200030"; //准高清
        }else if(mediaInfoDTO.getHeight() >= 848){
            templateId = "S00000001-200020"; //标清
        }else{
            templateId = "S00000001-200010"; //流畅
        }

        // 创建提交转码作业的请求
        SubmitJobsRequest request = new SubmitJobsRequest();
        request.setPipelineId("16578710314a42c9ac6679cbda4dc04b");

        JSONObject input = JSONUtil.createObj()
                .set("Bucket", inputBucket)
                .set("Location", "oss-cn-shanghai")
                .set("Object", inputObject)
                //.set("Referer", HttpUtils.getReferer()) //设置防盗链
                ;
        request.setInput(input.toJSONString(0));

        // 所有文字水印
        List<JSONObject> waterMarks = new ArrayList<>();
        // 文字水印配置
        String config = "{\"FontName\":\"SimSun\",\"FontSize\":48,\"FontColor\":\"Black\",\"Top\":10,\"Left\":10}";
        if(StrUtil.isNotEmpty(videoWatermarkConfig)){
            config = videoWatermarkConfig;
        }
        // apollo指定固定值，不指定使用动态计算
        if(StrUtil.isNotEmpty(videoWatermarkSpace)){
            watermarkConfigDto.setSpace(Integer.parseInt(videoWatermarkSpace));
        }

        //门店名称水印
        JSONObject storeName = JSONUtil.createObj().set("Type", "Text").set("TextWaterMark",
                JSONUtil.parseObj(config).set("FontSize", watermarkConfigDto.getFontSize())
                        .set("Content", Base64Utils.encodeToString(dto.getStoreName().getBytes(StandardCharsets.UTF_8))));
        waterMarks.add(storeName);

        // 门店地址太长时拆分2个水印
        String addr1 = dto.getStoreAddress();
        String addr2 = null;
        int len = 25;
        if(dto.getStoreAddress().length() > len) {
            addr1 = dto.getStoreAddress().substring(0, len);
            addr2 = dto.getStoreAddress().substring(len);
        }
        int rowHeight = watermarkConfigDto.getFontSize() + watermarkConfigDto.getSpace();
        int multiple = 1;
        JSONObject storeAddress = JSONUtil.createObj().set("Type", "Text").set("TextWaterMark",
                JSONUtil.parseObj(config).set("FontSize", watermarkConfigDto.getFontSize())
                        .set("Content", Base64Utils.encodeToString(addr1.getBytes(StandardCharsets.UTF_8)))
                        .set("Top", rowHeight));
        waterMarks.add(storeAddress);
        if(addr2 != null) {
            multiple++;
            JSONObject storeAddress2 = JSONUtil.createObj().set("Type", "Text").set("TextWaterMark",
                    JSONUtil.parseObj(config).set("FontSize", watermarkConfigDto.getFontSize())
                            .set("Content", Base64Utils.encodeToString(addr2.getBytes(StandardCharsets.UTF_8)))
                            .set("Top", rowHeight * multiple));
            waterMarks.add(storeAddress2);
        }

        //姓名日期水印
        multiple++;
        String nameAndTime = dto.getEmpName() + "  " + dto.getTimeStr();
        JSONObject empName = JSONUtil.createObj().set("Type", "Text").set("TextWaterMark",
                JSONUtil.parseObj(config).set("FontSize", watermarkConfigDto.getFontSize())
                        .set("Content", Base64Utils.encodeToString(nameAndTime.getBytes(StandardCharsets.UTF_8)))
                        .set("Top", rowHeight * multiple));
        waterMarks.add(empName);

        JSONObject output = JSONUtil.createObj()
                .set("OutputObject", outputObject)
                .set("TemplateId", templateId)
                .set("WaterMarks", waterMarks) //文档参数WaterMarks是错的
                ;
        request.setOutputs(JSONUtil.createArray().set(output).toJSONString(0));
        request.setOutputBucket(outputBucket);
        request.setOutputLocation("oss-cn-shanghai");
        try {
            return aliyunMtsService.submitJobs(request);
        } catch (Exception e) {
            log.error("视频加水印时异常", e);
            return false;
        }
    }

    public Map<String, String> getVideoWithWaterMark(List<String> ossUrls){
        Map<String, String> map = new HashMap<>();
        for(String ossUrl : ossUrls){
            String videoWithWaterMark = getVideoWithWaterMark(ossUrl);
            map.put(ossUrl, videoWithWaterMark);
        }
        return map;
    }

    public String getVideoWithWaterMark(String ossUrl){
        // 水印视频url
        int index = ossUrl.lastIndexOf("."); //后缀名.的位置
        String newVideoUrl = ossUrl.substring(0, index) + WATERMASK_MP4;
        boolean exist = ossService.doesObjectExist(newVideoUrl);
        return exist ? newVideoUrl : ossUrl;
    }

}
